// 1 导入react
import React from 'react'
import ReactDOM from 'react-dom'

// import PropTypes from 'prop-types'
// 引入css文件
import "./index.css"


/**
 * 组件的生命周期
 */

// 意义: 组件的生命周期有助于理解组件的运行方式 完成更复杂的组件功能 分析组件错误原因等
// 组件的生命周期:组件从被创建到挂载到页面中运行,到组件不用试卸载的过程
// 生命周期的每个阶段总是伴随着一些方法调用 这些方法就是生命周期的钩子函数
// 钩子函数的作用: 为开发人员在不同阶段操作组件提供了时机
// 只有类组件 才有生命周期


// 生命周期的三个阶段

// 创建时(挂载阶段)
// 执行时机 constructor render componentDidMount
// 更新时 render componentDidUpdate
// 卸载时 componentWillUnmont


// 创建时 (挂载阶段)
// 执行时机:组件创建时: (页面加载)

//  钩子函数            触发时机                        作用
//  construct         创建组件时,最先执行            1.初始化state 2.为事件处理程序绑定this
//  render            每次组件渲染都会触发           2.渲染UI (注意:不能调用setState())   
//  componentDidMont   组件挂载(完成DOM渲染后)       1.发送网络请求  2.DOM操作


// 更新时
// 执行时机 1.setState() 2.forceUpdate() 3.组件接收到更新的props
// 说明:以上三者任意一种变化 组件都会更新
// 执行顺序 render()->componentDidUpdate()

// 钩子函数             触发时机                作用
//  render          每次组件渲染都会触发        渲染UI(与挂职夹断是同一个render)
// componentDidUpdate   组件更新(完成DOM渲染)   1.发送网络请求 2.DOM操作 注意:如果setState() 必须放在一个if条件中

// 卸载阶段

// 执行时机: 组件从页面消失

//      钩子函数                     触发时机                       作用
//      componentWillUnmont        组件卸载(从页面消失)         执行清除工作(比如 定时器)


class App extends React.Component {

    constructor(props) {
        super(props)
        const title = document.getElementById('title')
        console.log(title)
        console.warn("生命周期钩子函数: constructor")
    }

    state = {
        count: 0
    }


    //1 进行DOM操作
    //2 发送ajax请求 后去远程数据
    componentDidMount() {
        console.warn("生命周期钩子函数 componentDidMount ")
    }


    componentWillUnmount() {
        console.warn('生命周期钩子函数 (componentWillUnmount)')
    }

    handlerClick = (e) => {
        this.setState({
            count: this.state.count + 1
        })

        //演示强制更新
        // this.forceUpdate()
    }

    render() {
        const { count } = this.state
        //render 里面调用setState()函数 会触发递归
        // this.setState({
        //     count: 2
        // })
        console.warn("生命周期钩子函数: render")
        return (
            <div>
                {
                    count > 3
                        ? (<p>豆豆被打死了</p>)
                        : <Counter count={count} />
                }
                <button onClick={this.handlerClick} >打豆豆</button>
            </div>
        )
    }

}


class Counter extends React.Component {

    // constructor(props) {
    //     super(props)
    //     console.log(props)
    // }
    render() {
        console.warn("(子组件)生命周期钩子函数: render")
        return (
            <div>
                <h2 id='title'>统计被打的次数: {this.props.count}</h2>
            </div>

        )
    }

    componentDidMount() {
        this.timerId = setInterval(() => {
            console.log("定时器执行")
        }, 1000);
    }

    // 注意: 如果要调用 setState() 更新状态 必须放在一个 if条件中
    // 因为: 如果直接调用setState() 更新状态 也会调至递归更新 setState->render->componentDidUpdate
    componentDidUpdate(preProps) {
        console.warn("(子组件)生命周期钩子函数: componentDidUpdate")

        // 会发生递归调用
        // this.setState({})
        //做法: 比较更新前后的prop是否相同,来决定是否重新渲染组件
        // 避免递归更新
        if (preProps.count !== this.props.count) {
            //发送ajax请求的代码
            this.setState({
            })
        }
        console.log("上一次 props", preProps)
        console.log("当前 props", this.props)
        const title = document.getElementById('title')
        console.log(title)
    }

    // 卸载组件 清理定时 避免内存泄漏
    componentWillUnmount() {
        console.warn('生命周期钩子函数 (componentWillUnmount)')
        clearInterval(this.timerId)
    }
} 


//3 渲染react元素
ReactDOM.render(
    <App
        // pageSize={11}
        colors={['red', "blue", "grent"]} />,
    document.getElementById('root'))
